import React, {useCallback, useEffect, useRef, useState} from "react";
import { CSSTransition } from "react-transition-group";
import { connect } from 'react-redux';

import { getSingerInfo, changeEnterLoading } from "./store/actionCreators";
import { Container } from "./style";
import { ImgWrapper, CollectButton, SongListWrapper, BgLayer } from "./style";
import Header from "../../baseUI/header/index";
import Scroll from "../../baseUI/scroll/index";
import SongsList from "../SongsList";
import { HEADER_HEIGHT } from "./../../api/config";
import Loading from "../../baseUI/loading";
import MusicNote from "../../baseUI/music-note";

function Singer (props) {
  const [showStatus, setShowStatus] = useState (true);

  const collectButton = useRef ();
  const imageWrapper = useRef ();
  const songScrollWrapper = useRef ();
  const songScroll = useRef ();
  const header = useRef ();
  const layer = useRef ();
  // 图片初始高度
  const initialHeight = useRef (0);

  // 往上偏移的尺寸,露出圆角
  const OFFSET = 5;

  const {
    artist: immutableArtist,
    songs: immutableSongs,
    loading,
  } = props;

  const { getSingerDataDispatch } = props;

  const artist = immutableArtist.toJS();
  const songs = immutableSongs.toJS();

  //
  useEffect(() => {
    const id = props.match.params.id;
    getSingerDataDispatch(id);
  }, []);

  /*由于歌曲列表是相对于 Container 绝对定位且 top 为 0,因此初始化时,我们将歌曲列表的 top 设置为整个图片的高度,正好处在图片下方,不然列表就会与图片重叠。*/
  useEffect(() => {
    let h = imageWrapper.current.offsetHeight;
    initialHeight.current = h;
    songScrollWrapper.current.style.top = `${h - OFFSET}px`;
    //把遮罩先放在下面,以裹住歌曲列表
    layer.current.style.top = `${h - OFFSET}px`;
    songScroll.current.refresh();
    // eslint-disable-next-line
  }, []);

  const setShowStatusFalse = useCallback (() => {
    setShowStatus (false);
  }, []);

  const handleScroll = useCallback (pos => {
    let height = initialHeight.current;
    const newY = pos.y;
    const imageDOM = imageWrapper.current;
    const buttonDOM = collectButton.current;
    const headerDOM = header.current;
    const layerDOM = layer.current;
    const minScrollY = -(height - OFFSET) + HEADER_HEIGHT;

    // 指的是滑动距离占图片高度的百分比
    const percent = Math.abs (newY /height);

    // 处理往下拉的情况,效果：图片放大,按钮跟着偏移
    if (newY > 0) {
      imageDOM.style["transform"] = `scale(${1 + percent})`;
      buttonDOM.style["transform"] = `translate3d(0, ${newY}px, 0)`;
      layerDOM.style.top = `${height - OFFSET + newY}px`;
    }

    // 往上滑动,但是遮罩还没超过 Header 部分
    else if (newY >= minScrollY) {
      layerDOM.style.top = `${height - OFFSET - Math.abs (newY)}px`;
      // 这时候保证遮罩的层叠优先级比图片高,不至于被图片挡住
      layerDOM.style.zIndex = 1;
      imageDOM.style.paddingTop = "75%";
      imageDOM.style.height = 0;
      imageDOM.style.zIndex = -1;
      // 按钮跟着移动且渐渐变透明
      buttonDOM.style["transform"] = `translate3d(0, ${newY}px, 0)`;
      buttonDOM.style["opacity"] = `${1 - percent * 2}`;
    }

    // 往上滑动,但是遮罩超过 Header 部分
    else if (newY < minScrollY) {
      // 往上滑动,但是超过 Header 部分
      layerDOM.style.top = `${HEADER_HEIGHT - OFFSET}px`;
      layerDOM.style.zIndex = 1;
      // 防止溢出的歌单内容遮住 Header
      headerDOM.style.zIndex = 100;
      // 此时图片高度与 Header 一致
      imageDOM.style.height = `${HEADER_HEIGHT}px`;
      imageDOM.style.paddingTop = 0;
      imageDOM.style.zIndex = 99;
    }
  }, []);

  const musicNoteRef = useRef();
  const musicAnimation = (x, y) => {
    musicNoteRef.current.startAnimation({ x, y });
  };

  return (
    <CSSTransition
      in={showStatus}
      timeout={300}
      classNames="fly"
      appear={true}
      unmountOnExit
      onExited={() => props.history.goBack ()}
    >
      <Container>
        <Header
          handleClick={setShowStatusFalse}
          title={artist.name}
          ref={header}
        />
        <ImgWrapper ref={imageWrapper} bgUrl={artist.picUrl}>
          <div className="filter"></div>
        </ImgWrapper>
        <CollectButton ref={collectButton}>
          <i className="iconfont">&#xe62d;</i>
          <span className="text"> 收藏 </span>
        </CollectButton>

        {/** 说明：在歌手页的布局中,歌单列表其实是没有自己的背景的,layerDOM 其实是起一个遮罩的作用,给歌单内容提供白色背景 因此在处理的过程中,随着内容的滚动,遮罩也跟着移动。*/}
        <BgLayer ref={layer}/>

        <SongListWrapper ref={songScrollWrapper}>
          <Scroll ref={songScroll} onScroll={handleScroll}>
            <SongsList
              songs={songs}
              showCollect={false}
              musicAnimation={musicAnimation}
            ></SongsList>
          </Scroll>
        </SongListWrapper>
        { loading ? (<Loading></Loading>) : null}
        <MusicNote ref={musicNoteRef}></MusicNote>
      </Container>
    </CSSTransition>
  )
}

// 映射 Redux 全局的 state 到组件的 props 上
const mapStateToProps = state => ({
  artist: state.getIn (["singerInfo", "artist"]),
  songs: state.getIn (["singerInfo", "songsOfArtist"]),
  loading: state.getIn (["singerInfo", "loading"]),
});
// 映射 dispatch 到 props 上
const mapDispatchToProps = dispatch => {
  return {
    getSingerDataDispatch (id) {
      dispatch (changeEnterLoading (true));
      dispatch (getSingerInfo (id));
    }
  };
};

// 将 ui 组件包装成容器组件
export default connect (mapStateToProps,mapDispatchToProps)(React.memo (Singer));
